package io.jft.doll.tcp

import com.alibaba.android.arouter.launcher.ARouter
import com.g.base.ActivityLifecycleHelper
import com.g.base.appContent
import com.g.base.extend.setTimeout
import com.g.base.extend.toast
import com.g.base.help.ProgressDialog
import com.g.base.help.d
import com.g.base.help.postSimpleNotify
import io.jft.doll.R
import io.jft.doll.event.AppointmentCleanEvent
import io.jft.doll.event.NotifyUrl
import io.jft.doll.room.database.AppDatabase
import io.jft.doll.room.repository.RoomRepository
import io.jft.doll.router.RouterPage
import io.jft.doll.tcp.event.TcpData
import io.jft.doll.weidget.TimeDownDialog
import io.netty.buffer.ByteBufAllocator
import io.netty.buffer.EmptyByteBuf
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.nio.charset.Charset

/**
 * Created by G on 2018/1/1 0001.
 */
object TcpHelp {
    private var currentAppointmentRoomId = "" //服务器返回的我当前预约的房间ID
    private var currentBlockAction = CurrentBlockAction.NothingDoing //当前在执行的阻塞操作
    private var justStartGame = false //预约到开始玩的过程中不再通知

    private val progressDialog by lazy { ProgressDialog() }

    fun init() {
        EventBus.getDefault().register(this)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onTcpReceive(ev: TcpData) {
        val data = ev.data
        when (ev.command) {
        //预约响应
            TcpC.COMD_REP_APPOINTMENT -> {
                if (currentBlockAction == CurrentBlockAction.AppointmentRoom) {
                    currentBlockAction = CurrentBlockAction.NothingDoing
                    justStartGame = false
                    when (data.getByte(0).toInt()) {
                        1 -> {
                            RoomRepository.appointmentRoom(currentAppointmentRoomId)
                            val roomSync = AppDatabase.instant.getRoomDao().getRoomSync(currentAppointmentRoomId)!!
                            if (roomSync.queued == 0) {
                                justStartGame = true
                                timeoutProgressDialog("准备开始游戏中~", "开始游戏超时了~", 15000L)
                            } else {
                                dismissDialog()
                                appContent.toast("预约成功")
                            }
                        }
                        0 -> {
                            cleanAppointmentStatus(false)
                            progressDialog.setFiled("预约失败,余额不足~") { it.dismiss(true) }
                        }
                        2 -> {
                            cleanAppointmentStatus(false)
                            progressDialog.setFiled("预约失败,娃娃机异常~") { it.dismiss(true) }
                        }
                    }
                } else {
                    cleanAppointmentStatus()
                    appContent.toast("预约状态错误~ code:$currentBlockAction")
                }
            }
        //房间状态变化
            TcpC.COMD_REP_ROOMSTATUS_CHANGE -> {
                val roomId = data.getCharSequence(1, data.readableBytes() - 1, Charset.defaultCharset()).toString()
                val roomStatus = if (data.getByte(0).toInt() == 3) 0 else {
                    if (currentAppointmentRoomId == roomId)
                        cleanAppointmentStatus(true)
                    2
                }
                d("TcpC.COMD_REP_ROOMSTATUS_CHANGE roomId $roomId roomStatus $roomStatus")
                RoomRepository.changeRoomStats(roomId, status = roomStatus)
            }
        //排队人数变化
            TcpC.COMD_REP_QUENED_CHANGE -> {
                val roomId = data.getCharSequence(2, data.readableBytes() - 2, Charset.defaultCharset()).toString()
                val queue = data.getShort(0).toInt()
                d("TcpC.COMD_REP_QUENED_CHANGE roomId $roomId queue $queue")
                RoomRepository.changeQueue(roomId, queue = queue, isAppointment = false)
            }
        //排队名次变化
            TcpC.COMD_REP_MY_QUNEND_CHANGE -> {
                val roomId = data.getCharSequence(2, data.readableBytes() - 2, Charset.defaultCharset()).toString()
                val queue = data.getShort(0).toInt()
                currentAppointmentRoomId = roomId
                d("TcpC.COMD_REP_MY_QUNEND_CHANGE roomId $roomId queue $queue")
                RoomRepository.changeQueue(roomId, queue = queue, isAppointment = true)
            }
        //轮到通知
            TcpC.COMD_REP_TURN_YOUT -> {
                turnYou()
            }
        //游戏操作TOKEN
            TcpC.COMD_TOKEN -> {
                postSimpleNotify(NotifyUrl.UserRemaining)
                if (currentBlockAction == CurrentBlockAction.StartGame && !currentAppointmentRoomId.isEmpty()) {
                    dismissDialog()
                    setTimeout(64L) {
                        currentBlockAction = CurrentBlockAction.GameResult
                        val token = ByteArray(data.readableBytes())
                        data.readBytes(token)
                        ARouter.getInstance().build(RouterPage.RoomActivity).withString("roomId", currentAppointmentRoomId).withObject("token", token).navigation(appContent)
                    }
                } else {
                    cleanAppointmentStatus()
                    appContent.toast("开始玩游戏状态错误~ code:$currentBlockAction")
                }
            }
        //返回异常
            TcpC.COMD_REP_EXCEPTION -> {
                if (currentBlockAction == CurrentBlockAction.StartGame) {
                    currentBlockAction = CurrentBlockAction.NothingDoing
                    if (data.getByte(0).toInt() == 1) {
                        cleanAppointmentStatus(false)
                        progressDialog.setFiled("余额不足,开始游戏失败啦~ sad!") { }
                    } else {
                        cleanAppointmentStatus(false)
                        progressDialog.setFiled("房间异常,开始游戏失败啦~ sad!") { }
                    }
                } else {
                    cleanAppointmentStatus()
                    appContent.toast("开始玩游戏异常状态错误~ code:$currentBlockAction")
                }
            }
        //返回数量
            TcpC.COMD_REP_AMOUNT -> {
                val amount = data.getByte(0).toInt()
                onAmountReturn(amount)
            }
        }
    }

    //预约房间 || 取消预约房间
    fun appointmentRoom(roomId: String, apm: Boolean) {
        when {
            roomId.isEmpty() -> appContent.toast("房间号错误 操作失败~")
            apm -> {
                justStartGame = false
                currentBlockAction = CurrentBlockAction.AppointmentRoom
                currentAppointmentRoomId = roomId
                timeoutProgressDialog("正在为您预约中...", "预约房间超时了~")
                tcpClient.writeAndFlush(TcpData(TcpC.COMD_APPOINTMENT, tcpClient.createBuffer().apply { writeCharSequence(roomId as CharSequence, Charset.defaultCharset()) })) {
                    if (it.isNotEmpty()) {
                        cleanAppointmentStatus(false)
                        progressDialog.setFiled(it) { it.dismiss() }
                    }
                }
            }
            else -> {
                currentBlockAction = CurrentBlockAction.AbortAppointmentRoom
                currentAppointmentRoomId = roomId
                cleanAppointmentStatus()
            }
        }
    }

    private fun turnYou() {
        if (currentAppointmentRoomId.isEmpty()) {
            cleanAppointmentStatus()
        } else {
            //房间没有人在玩 直接开始玩游戏!
            if (justStartGame) {
                tcpClient.writeAndFlush(TcpData(TcpC.COMD_TURN_YOUT, tcpClient.createBuffer().writeByte(0x01))) {
                    if (it.isEmpty()) {
                        timeoutProgressDialog("正在对房间进行清理~", "房间清理失败了~稍后再试吧")
                        currentBlockAction = CurrentBlockAction.StartGame
                    } else {
                        appContent.toast(it)
                        cleanAppointmentStatus()
                    }
                }
            } else {
                dismissDialog()
                //房间已经有人在玩了
                TimeDownDialog(ActivityLifecycleHelper.getLatestActivity()!!.layoutInflater,
                        "开抓啦~!", "轮到你开始抓娃娃了~", "赶紧开始", "我放弃")
                        .apply {
                            setOnClickListener {
                                when (it.id) {
                                    R.id.negative -> {
                                        cleanAppointmentStatus()
                                    }
                                    R.id.positive -> {
                                        tcpClient.writeAndFlush(TcpData(TcpC.COMD_TURN_YOUT, tcpClient.createBuffer().writeByte(0x01))) {
                                            if (it.isEmpty()) {
                                                currentBlockAction = CurrentBlockAction.StartGame
                                                timeoutProgressDialog("正在对房间进行清理~", "房间清理失败了~稍后再试吧")
                                            } else {
                                                cleanAppointmentStatus(false)
                                                progressDialog.setFiled(it) { it.dismiss() }
                                            }
                                        }
                                    }
                                }
                            }
                            start()
                        }
            }
        }
    }

    fun onAmountReturn(amount: Int) {
        if (currentBlockAction != CurrentBlockAction.GameResult)
            return

        currentBlockAction = CurrentBlockAction.NothingDoing
        dismissDialog()
        val content = when {
            amount > 0 -> "恭喜你,抓到了娃娃~"
            amount < 0 -> "很抱歉,没有收到返回结果! 请稍后再我的游戏记录里面查看吧~!"
            else -> "很遗憾没有抓到娃娃 再接再厉吧~"
        }

        TimeDownDialog(ActivityLifecycleHelper.getLatestActivity()!!.layoutInflater,
                "游戏结果~!", content, "再来一局", "我放弃")
                .apply {
                    setOnClickListener {
                        when (it.id) {
                            R.id.negative -> {
                                cleanAppointmentStatus()
                            }
                            R.id.positive -> {
                                dismissDialog()
                                justStartGame = true
                                turnYou()
                            }
                        }
                    }
                    start()
                }
    }

    private var timeoutDialogTimeout: (() -> Unit)? = null
    private fun timeoutProgressDialog(msg: String, timeOutMsg: String, timeout: Long = 5000L) {
        timeoutDialogTimeout?.invoke()
        progressDialog.setStart(msg)
        timeoutDialogTimeout = setTimeout(timeout) {
            if (progressDialog.dialog?.isShowing == true && progressDialog.isLoading) {
                cleanAppointmentStatus(false)
                progressDialog.setFiled(timeOutMsg) {
                    it.dismiss(true)
                }
            }
        }
    }

    private fun dismissDialog() {
        timeoutDialogTimeout?.invoke()
        progressDialog.dismiss()
    }

    //取消当前的预约状态
    private fun cleanAppointmentStatus(dismissDialog: Boolean = true) {
        if (currentAppointmentRoomId.isNotEmpty()) {
            RoomRepository.abortAppointmentRoom(currentAppointmentRoomId)
        }
        //取消预约 拒绝玩游戏
        tcpClient.writeAndFlush(TcpData(TcpC.COMD_TURN_YOUT, tcpClient.createBuffer().writeByte(0x00))) {}
        tcpClient.writeAndFlush(TcpData(TcpC.COMD_ABORD_APPOINTMENT_CHANGE, EmptyByteBuf(ByteBufAllocator.DEFAULT))) {}

        //防止在游戏(房间)里面卡主 不能退出
        EventBus.getDefault().post(AppointmentCleanEvent())

        timeoutDialogTimeout?.invoke()
        currentBlockAction = CurrentBlockAction.NothingDoing
        currentAppointmentRoomId = ""
        justStartGame = false

        if (dismissDialog) dismissDialog()
    }
}

object CurrentBlockAction {
    const val NothingDoing = -1
    const val AppointmentRoom = 0
    const val AbortAppointmentRoom = 1
    const val StartGame = 2
    const val GameResult = 3
}